package com.rickpan.controller;

import com.rickpan.common.ApiResponse;
import com.rickpan.dto.request.CreatePaymentOrderRequest;
import com.rickpan.dto.response.PaymentOrderResponse;
import com.rickpan.dto.response.VipStatusResponse;
import com.rickpan.dto.response.VipSubscriptionResponse;
import com.rickpan.entity.PaymentOrder;
import com.rickpan.entity.User;
import com.rickpan.entity.VipSubscription;
import com.rickpan.repository.UserRepository;
import com.rickpan.service.PaymentService;
import com.rickpan.service.VipFeatureService;
import com.rickpan.service.VipSubscriptionService;
import com.rickpan.utils.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import jakarta.validation.Valid;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * VIP会员系统控制器
 */
@RestController
@RequestMapping("/api/vip")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "VIP会员系统", description = "VIP会员相关接口")
public class VipController {

    private final PaymentService paymentService;
    private final VipSubscriptionService subscriptionService;
    private final VipFeatureService featureService;
    private final UserRepository userRepository;

    /**
     * 创建支付订单
     */
    @PostMapping("/orders")
    @Operation(summary = "创建支付订单", description = "创建VIP套餐支付订单")
    public ApiResponse<PaymentOrderResponse> createPaymentOrder(
            @Valid @RequestBody CreatePaymentOrderRequest request) {

        Long userId = SecurityUtils.getCurrentUserId();
        PaymentOrder.PlanType planType = PaymentOrder.PlanType.valueOf(request.getPlanType());
        
        PaymentOrder order = paymentService.createPaymentOrder(userId, planType);

        PaymentOrderResponse response = PaymentOrderResponse.builder()
            .id(order.getId())
            .orderNo(order.getOrderNo())
            .planType(order.getPlanType().name())
            .amount(order.getAmount())
            .status(order.getStatus().name())
            .paymentMethod(order.getPaymentMethod().name())
            .createdAt(order.getCreatedAt())
            .expiresAt(order.getExpiresAt())
            .build();

        return ApiResponse.success(response);
    }

    /**
     * 支付回调接口 (支付宝/微信)
     */
    @PostMapping("/callback/payment")
    @Operation(summary = "支付回调", description = "处理第三方支付平台回调")
    public String handlePaymentCallback(@RequestParam Map<String, String> params) {
        try {
            String orderNo = params.get("out_trade_no");
            String tradeNo = params.get("trade_no");
            String tradeStatus = params.get("trade_status");

            log.info("收到支付回调: orderNo={}, tradeNo={}, status={}", orderNo, tradeNo, tradeStatus);

            paymentService.handlePaymentCallback(orderNo, tradeNo, tradeStatus);
            return "success";
        } catch (Exception e) {
            log.error("支付回调处理失败", e);
            return "fail";
        }
    }

    /**
     * 获取用户VIP状态
     */
    @GetMapping("/status")
    @Operation(summary = "获取VIP状态", description = "获取当前用户的VIP状态信息")
    public ApiResponse<VipStatusResponse> getVipStatus() {
        Long userId = SecurityUtils.getCurrentUserId();
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户不存在"));

        Long daysLeft = null;
        if (user.getVipExpireTime() != null) {
            daysLeft = ChronoUnit.DAYS.between(LocalDateTime.now(), user.getVipExpireTime());
            if (daysLeft < 0) daysLeft = 0L;
        }

        double storageUsagePercentage = 0.0;
        if (user.getStorageQuota() > 0) {
            storageUsagePercentage = (user.getStorageUsed() * 100.0) / user.getStorageQuota();
        }

        VipStatusResponse response = VipStatusResponse.builder()
            .userType(user.getUserType().name())
            .isVip(user.isVip())
            .vipExpireTime(user.getVipExpireTime())
            .daysLeft(daysLeft)
            .storageQuota(user.getStorageQuota())
            .storageUsed(user.getStorageUsed())
            .storageUsagePercentage(storageUsagePercentage)
            .build();

        return ApiResponse.success(response);
    }

    /**
     * 获取功能使用统计
     */
    @GetMapping("/feature-usages")
    @Operation(summary = "获取功能使用统计", description = "获取当前用户各功能的使用情况")
    public ApiResponse<List<VipFeatureService.FeatureUsageVO>> getFeatureUsages() {
        Long userId = SecurityUtils.getCurrentUserId();
        List<VipFeatureService.FeatureUsageVO> usages = featureService.getUserFeatureUsages(userId);
        return ApiResponse.success(usages);
    }

    /**
     * 检查功能使用权限
     */
    @GetMapping("/check-feature/{featureCode}")
    @Operation(summary = "检查功能权限", description = "检查用户是否可以使用指定功能")
    public ApiResponse<Boolean> checkFeature(@PathVariable String featureCode) {
        Long userId = SecurityUtils.getCurrentUserId();
        boolean canUse = featureService.canUseFeature(userId, featureCode);
        return ApiResponse.success(canUse);
    }

    /**
     * 获取剩余使用量
     */
    @GetMapping("/remaining-usage/{featureCode}")
    @Operation(summary = "获取剩余使用量", description = "获取指定功能的剩余使用量")
    public ApiResponse<Integer> getRemainingUsage(@PathVariable String featureCode) {
        Long userId = SecurityUtils.getCurrentUserId();
        int remaining = featureService.getRemainingUsage(userId, featureCode);
        return ApiResponse.success(remaining);
    }

    /**
     * 获取用户订单列表
     */
    @GetMapping("/orders")
    @Operation(summary = "获取订单列表", description = "获取当前用户的支付订单列表")
    public ApiResponse<Page<PaymentOrderResponse>> getUserOrders(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "createdAt") String sortBy,
            @RequestParam(defaultValue = "desc") String sortDirection) {
        
        Long userId = SecurityUtils.getCurrentUserId();
        
        // 构建分页参数
        Sort.Direction direction = sortDirection.equalsIgnoreCase("desc") ? 
            Sort.Direction.DESC : Sort.Direction.ASC;
        Pageable pageable = PageRequest.of(page, size, Sort.by(direction, sortBy));
        
        Page<PaymentOrder> orderPage = paymentService.getUserOrdersPage(userId, pageable);
        Page<PaymentOrderResponse> responsePage = orderPage.map(this::convertToPaymentOrderResponse);
        
        return ApiResponse.success(responsePage);
    }

    /**
     * 获取用户订阅列表
     */
    @GetMapping("/subscriptions")
    @Operation(summary = "获取订阅列表", description = "获取当前用户的VIP订阅列表")
    public ApiResponse<List<VipSubscriptionResponse>> getUserSubscriptions() {
        Long userId = SecurityUtils.getCurrentUserId();
        List<VipSubscription> subscriptions = subscriptionService.getUserSubscriptions(userId);

        List<VipSubscriptionResponse> responses = subscriptions.stream()
            .map(this::convertToSubscriptionResponse)
            .collect(Collectors.toList());

        return ApiResponse.success(responses);
    }

    /**
     * 取消订单
     */
    @PostMapping("/orders/{orderNo}/cancel")
    @Operation(summary = "取消订单", description = "取消指定的支付订单")
    public ApiResponse<Void> cancelOrder(@PathVariable String orderNo) {
        // 验证订单所有权
        PaymentOrder order = paymentService.getOrderByOrderNo(orderNo)
            .orElseThrow(() -> new RuntimeException("订单不存在"));
        
        Long userId = SecurityUtils.getCurrentUserId();
        if (!order.getUserId().equals(userId)) {
            throw new RuntimeException("无权限操作此订单");
        }

        paymentService.cancelOrder(orderNo);
        return ApiResponse.success();
    }

    /**
     * 取消订阅 (立即降级)
     */
    @PostMapping("/subscriptions/{subscriptionId}/cancel")
    @Operation(summary = "取消订阅", description = "取消VIP订阅并立即降级为BASIC用户")
    public ApiResponse<Void> cancelSubscription(@PathVariable Long subscriptionId) {
        Long userId = SecurityUtils.getCurrentUserId();
        subscriptionService.cancelSubscription(userId, subscriptionId);
        return ApiResponse.success();
    }

    /**
     * 转换为支付订单响应对象
     */
    private PaymentOrderResponse convertToPaymentOrderResponse(PaymentOrder order) {
        return PaymentOrderResponse.builder()
            .id(order.getId())
            .orderNo(order.getOrderNo())
            .planType(order.getPlanType().name())
            .amount(order.getAmount())
            .status(order.getStatus().name())
            .paymentMethod(order.getPaymentMethod().name())
            .createdAt(order.getCreatedAt())
            .paidAt(order.getPaidAt())
            .expiresAt(order.getExpiresAt())
            .remark(order.getRemark())
            .build();
    }

    /**
     * 转换为订阅响应对象
     */
    private VipSubscriptionResponse convertToSubscriptionResponse(VipSubscription subscription) {
        Long daysLeft = ChronoUnit.DAYS.between(LocalDateTime.now(), 
            subscription.getEndDate().atStartOfDay());
        if (daysLeft < 0) daysLeft = 0L;

        String planName = subscription.getPlanType() == PaymentOrder.PlanType.MONTHLY_VIP 
            ? "月度VIP" : "年度VIP";

        return VipSubscriptionResponse.builder()
            .id(subscription.getId())
            .userId(subscription.getUserId())
            .orderId(subscription.getOrderId())
            .planType(subscription.getPlanType().name())
            .planName(planName)
            .startDate(subscription.getStartDate())
            .endDate(subscription.getEndDate())
            .status(subscription.getStatus().name())
            .statusDescription(subscription.getStatus().getDescription())
            .autoRenew(subscription.getAutoRenew())
            .originalAmount(subscription.getOriginalAmount())
            .discountAmount(subscription.getDiscountAmount())
            .actualAmount(subscription.getActualAmount())
            .createdAt(subscription.getCreatedAt())
            .daysLeft(daysLeft)
            .build();
    }
}